本文重点阐述了xgboost和lightgbm的主要参数和调参技巧,其理论部分可见集成学习,以下内容主要来自xgboostLightGBM的官方文档。

xgboost

Xgboost参数主要分为三大类:
General Parameters(通用参数):设置整体功能
Booster Parameters(提升参数):选择你每一步的booster(树or回归)
Learning Task Parameters(学习任务参数):指导优化任务的执行

General Parameters(通用参数)

  • booster [default=gbtree]
    选择每次迭代过程中需要运行的模型,一共有两种选择:gbtree和gblinear。gbtree使用基于树的模型进行提升计算,gblinear使用线性模型进行提升计算。缺省值为gbtree
  • silent [default=0]
    取0时表示打印出运行时信息,取1时表示以缄默方式运行,不打印运行时信息。缺省值为0
  • nthread [default to maximum number of threads available if not set]
    XGBoost运行时的线程数。缺省值是当前系统可以获得的最大线程数

剩余两个参数是Xgboost自动指定的,无需设置。

Booster Parameters(提升参数)

虽然有两种类型的booster,但是我们这里只介绍tree。因为tree的性能比线性回归好得多,因此我们很少用线性回归。

  • eta [default=0.3]
    学习率,可以缩减每一步的权重值,使得模型更加健壮:
    典型值一般设置为:0.01-0.2
    取值范围为:[0,1]
  • gamma [default=0]
    这个指定了一个结点被分割时,所需要的最小损失函数减小的大小。这个值一般来说需要根据损失函数来调整。
    range: [0,∞]
  • max_depth [default=6]
    数的最大深度。缺省值为6
    这个可以用来控制过拟合,典型值是3-10。
    取值范围为:[1,∞]
  • min_child_weight [default=1]
    孩子节点中最小的样本权重和。在现行回归模型中,这个参数是指建立每个模型所需要的最小样本数。该值越大算法越保守
    取值范围为: [0,∞]
  • subsample [default=1]
    用于训练模型的子样本占整个样本集合的比例。如果设置为0.5则意味着XGBoost将随机的冲整个样本集合中随机的抽取出50%的子样本建立树模型,这能够防止过拟合。
    取值范围为:(0,1]
  • colsample_bytree [default=1]
    在建立树时对特征采样的比例。缺省值为1
    取值范围:(0,1]
  • lambda [default=1, alias: reg_lambda]
    L2正则化。
  • alpha [default=0, alias: reg_alpha]
    L1正则化,主要用在数据维度很高的情况下,可以提高运行速度。
  • scale_pos_weight, [default=1]
    在类别高度不平衡的情况下,将参数设置大于0,可以加快收敛。

Learning Task Parameters(学习任务参数)

  • objective [ default=reg:linear ]
    定义学习任务及相应的学习目标,可选的目标函数如下:
    “reg:linear” –线性回归。
    “reg:logistic” –逻辑回归。
    “binary:logistic” –二分类的逻辑回归问题,输出为概率。
    “binary:logitraw” –二分类的逻辑回归问题,输出的结果为wTx。
    “count:poisson” –计数问题的poisson回归,输出结果为poisson分布。
    “multi:softmax” –让XGBoost采用softmax目标函数处理多分类问题,同时需要设置参数num_class(类别个数)
    “multi:softprob” –和softmax一样,但是输出的是ndata * nclass的向量,可以将该向量reshape成ndata行nclass列的矩阵。每行数据表示样本所属于每个类别的概率。

  • eval_metric [ default according to objective ]
    评估方法,主要用来验证数据,根据一个学习目标会默认分配一个评估指标
    “rmse”:均方根误差(回归任务)
    “logloss”:
    “error”
    “mlogloss”
    “merror”
    “auc”

  • seed [ default=0 ]
    随机数的种子。缺省值为0

调参方法

调参的通用方法:
选择一个相对较高的学习率。通常来说学习率设置为0.1。但是对于不同的问题可以讲学习率设置在0.05-0.3。通过交叉验证来寻找符合学习率的最佳树的个数。
当确定好学习率与最佳树的个数时,调整树的某些特定参数。比如:max_depth, min_child_weight, gamma, subsample, colsample_bytree
调整正则化参数 ,比如: lambda, alpha。这个主要是为了减少模型复杂度和提高运行速度的。适当地减少过拟合。
降低学习速率,选择最优参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
import xgboost as xgb
params={
'booster':'gbtree',
'objective': 'multi:softmax', #多分类的问题
'num_class':10, # 类别数,与 multisoftmax 并用
'gamma':0.1, # 用于控制是否后剪枝的参数,越大越保守,一般0.1、0.2这样子。
'max_depth':12, # 构建树的深度,越大越容易过拟合
'lambda':2, # 控制模型复杂度的权重值的L2正则化项参数,参数越大,模型越不容易过拟合。
'subsample':0.7, # 随机采样训练样本
'colsample_bytree':0.7, # 生成树时进行的列采样
'min_child_weight':3,
# 这个参数默认是 1,是每个叶子里面 h 的和至少是多少,对正负样本不均衡时的 0-1 分类而言
#,假设 h 在 0.01 附近,min_child_weight 为 1 意味着叶子节点中最少需要包含 100 个样本。
#这个参数非常影响结果,控制叶子节点中二阶导的和的最小值,该参数值越小,越容易 overfitting。
'silent':0 ,#设置成1则没有运行信息输出,最好是设置为0.
'eta': 0.007, # 如同学习率
'seed':1000,
'nthread':7,# cpu 线程数
#'eval_metric': 'auc'
}
model = xgb.train(plst, xgb_train, num_rounds, watchlist,early_stopping_rounds=100)
model.save_model('./model/xgb.model') # 用于存储训练出的模型
print "best best_ntree_limit",model.best_ntree_limit


#Grid seach on subsample and max_features

param_test1 = {
'max_depth':list(range(3,10,2)),
'min_child_weight':list(range(1,6,2))
}
"""
参数说明;
n_estimators:基学习器的个数(第一步得到)
scoring:得分排名依据,因为是越高越好,这是mean_squared_error取负

"""

gsearch1 = GridSearchCV(estimator = XGBRegressor( learning_rate =0.1, n_estimators=33, max_depth=5,
min_child_weight=1, gamma=0, subsample=0.8, colsample_bytree=0.8,
objective= 'gpu:reg:linear', nthread=4, scale_pos_weight=1, seed=27),
param_grid = param_test1, scoring='neg_mean_squared_error',n_jobs=1,iid=False, cv=5)
gsearch1.fit(X,y)
print(gsearch1.cv_results_, gsearch1.best_params_, gsearch1.best_score_)


#进一步探索参数max_depth,min_child_weight(前面得到最好的是{‘max_depth’: 5, ‘min_child_weight’: 1})
#Grid seach on subsample and max_features

param_test2 = {
'max_depth':[4,5,6],
'min_child_weight':[0,1,2] #范围: [0,∞]
}
gsearch2 = GridSearchCV(estimator = XGBRegressor( learning_rate=0.1, n_estimators=33, max_depth=5,
min_child_weight=2, gamma=0, subsample=0.8, colsample_bytree=0.8,
objective= 'gpu:reg:linear', nthread=4, scale_pos_weight=1,seed=27),
param_grid = param_test2, scoring='neg_mean_squared_error',n_jobs=1,iid=False, cv=5)
gsearch2.fit(X,y)
print(gsearch2.cv_results_, gsearch2.best_params_, gsearch2.best_score_)
#继续搜索参数min_child_weight {‘max_depth’: 5, ‘min_child_weight’: 2}
#Grid seach on subsample and max_features
#-3775.018211540544
param_test2b = {
'min_child_weight':[2,4,6,8]
}
gsearch2b = GridSearchCV(estimator = XGBRegressor( learning_rate=0.1, n_estimators=33, max_depth=5,
min_child_weight=2, gamma=0, subsample=0.8, colsample_bytree=0.8,
objective= 'gpu:reg:linear', nthread=4, scale_pos_weight=1,seed=27),
param_grid = param_test2b, scoring='neg_mean_squared_error',n_jobs=1,iid=False, cv=5)
gsearch2b.fit(X,y)
print(gsearch2b.cv_results_, gsearch2b.best_params_, gsearch2b.best_score_)
#调整参数gamma,range: [0,∞],default=0
#Grid seach on subsample and max_features
#在树的叶子节点上进行进一步划分所需的最小损失。越大,算法就越保守。
param_test3 = {
'gamma':[i/10.0 for i in range(0,5)]
}
gsearch3 = GridSearchCV(estimator = XGBRegressor( learning_rate =0.1, n_estimators=33, max_depth=5,
min_child_weight=2, gamma=0, subsample=0.8, colsample_bytree=0.8,
objective= 'gpu:reg:linear', nthread=4, scale_pos_weight=1,seed=27),
param_grid = param_test3, scoring='neg_mean_squared_error',n_jobs=1,iid=False, cv=5)
gsearch3.fit(X,y)
print(gsearch3.cv_results_, gsearch3.best_params_, gsearch3.best_score_)
#调整参数subsample,colsample_bytree
#Grid seach on subsample and max_features
param_test4 = {
'subsample':[i/10.0 for i in range(6,10)],
'colsample_bytree':[i/10.0 for i in range(6,10)]
}
gsearch4 = GridSearchCV(estimator = XGBRegressor( learning_rate =0.1, n_estimators=53, max_depth=5,
min_child_weight=2, gamma=0, subsample=0.8, colsample_bytree=0.8,
objective= 'gpu:reg:linear', nthread=4, scale_pos_weight=1,seed=27),
param_grid = param_test4, scoring='neg_mean_squared_error',n_jobs=1,iid=False, cv=5)
a=gsearch4.fit(train[predictors],train[target])
print(a)
gsearch4.fit(X,y)
print(gsearch4.cv_results_, gsearch4.best_params_, gsearch4.best_score_)

LightGBM

LightGBM中的主要调节的参数包括核心参数、学习控制参数、IO 参数、目标参数、度量参数等。

Core Parameters(核心参数)

  • task [default=train]
    数据的用途 选择 train,predict或者convert_model(将模型文件转换成 if-else 格式):
  • objective [default=regression]
    模型的用途
    ‘regression’表示回归任务,但是使用L2损失函数。
    ‘regression_l1’:表示回归任务,但是使用L1损失函数。
    ‘huber’: 表示回归任务,但是使用huber 损失函数。
    ‘fair’: 表示回归任务,但是使用fair 损失函数。
    ‘binary’: 表示二分类任务,使用对数损失函数作为目标函数。
    ‘multiclass’: 表示多分类任务,使用softmax 函数作为目标函数。必须设置num_class 参数
    ‘multiclassova’ : 表示多分类任务,使用one-vs-all 的二分类目标函数。必须设置num_class 参数
    ‘xentropy’: 目标函数为交叉熵(同时具有可选择的线性权重)。要求标签是[0,1] 之间的数值。
    ‘xentlambda’ : 替代了参数化的cross_entropy 。要求标签是[0,1]之间的数值。
  • boosting [default=gbdt]
    给出基学习器模型算法。可以为:
    ‘gbdt’: 表示传统的梯度提升决策树。默认值为’gbdt’
    ‘rf’: 表示随机森林。
    ‘dart’: 表示带dropout 的gbdt
    goss:表示Gradient-based One-Side Sampling 的gbdt (基于梯度的单侧采样)
  • data, [default=””]
    训练数据, LightGBM 将会使用这个数据进行训练
  • valid, [default=””]
    验证/测试 数据, LightGBM 将输出这些数据的度量
  • num_iterations, [default=100]
    boosting的迭代次数。
    • 对于python/R包,该参数是被忽略的。对于python,使用train()/cv()的输入参数num_boost_round来代替。
  • learning_rate, [default=0.1]
    学习率
  • num_leaves, [default=31]
    一棵树上的叶子数。
  • tree_learner,[default=serial]
    主要用于并行学习。 默认为’serial’单台机器。
  • num_threads, [default=OpenMP_default]
    LightGBM 的线程数
  • device, [default=cpu]
    指定计算设备。默认为’cpu’。 可以为’gpu’,’cpu’。
    • 为了加快学习速度,GPU 默认使用32位浮点数来求和。你可以设置gpu_use_dp=True 来启动64位浮点数,但是它会使得训练速度降低。

Learning Control Parameters(学习控制参数)

  • max_depth, [default=-1]
    限制树模型的最大深度。如果小于0,则表示没有限制。
  • min_data_in_leaf, [default=20]
    一个叶子上数据的最小数量. 可以用来处理过拟合.
  • min_sum_hessian_in_leaf, [default=1e-3]
    一个叶子上的最小 hessian 和也就是叶节点样本权重之和的最小值), 类似于 min_data_in_leaf, 可以用来处理过拟合.
  • feature_fraction, [default=1.0]
    如果小于1.0,则lightgbm 会在每次迭代中随机选择部分特征。如0.8 表示:在每棵树训练之前选择80% 的特征来训练。
  • feature_fraction_seed, [default=2]
    feature_fraction 的随机数种子
  • bagging_fraction, [default=1]
    类似于 feature_fraction, 但是它将在不进行重采样的情况下随机选择部分数据
    • Note: 为了启用 bagging, bagging_freq 应该设置为非零值
  • bagging_freq, [default=0]
    bagging 的频率, 0 意味着禁用 bagging. k 意味着每 k 次迭代执行bagging
  • bagging_seed , [default=3]
    bagging 随机数种子
  • early_stopping_round, [default=0]
    如果一个验证集的度量在 early_stopping_round 循环中没有提升, 将停止训练
  • lambda_l1, [default=0]
    L1 正则
  • lambda_l2, [default=0]
    L2 正则
  • min_split_gain, [default=0]
    执行切分的最小增益
  • lambda_l1, [default=0]
    L1 正则
  • feature_fraction_seed, [default=2]
    feature_fraction 的随机数种子
  • feature_fraction_seed, [default=2]
    feature_fraction 的随机数种子
  • feature_fraction_seed, [default=2]
    feature_fraction 的随机数种子

IO Parameters(IO 参数)

  • max_bin, [default=255]
    表示最大的桶的数量。lightgbm 会根据它来自动压缩内存。如max_bin=255 时,则lightgbm 将使用uint8 来表示特征的每一个值。
  • min_data_in_bin, [default=3]
    表示每个桶的最小样本数。该方法可以避免出现一个桶只有一个样本的情况。
  • data_random_seed, [default=1]
    表示并行学习数据分隔中的随机数种子。默认为1它不包括特征并行。
  • output_model, [default=LightGBM_model.txt]
    表示训练中输出的模型被保存的文件的文件名。
  • input_model, [default=””]
    表示输入模型的文件的文件名。默认空字符串。对于prediction任务,该模型将用于预测数据,对于train任务,训练将从该模型继续
  • output_result, [default=LightGBM_predict_result.txt]
    prediction 任务的预测结果文件名
  • pre_partition, [default=false]
    用于并行学习(不包括功能并行). 如果为true,则不同的机器使用不同的partition 来训练。
  • is_sparse, [default=true]
    用于 enable/disable 稀疏优化. 设置 false 就禁用稀疏优化
  • two_round, [default=false]
    一个布尔值,指示是否启动两次加载。默认值为False,表示只需要进行一次加载。默认情况下,lightgbm 会将数据文件映射到内存,然后从内存加载特征,这将提供更快的数据加载速度。但是当数据文件很大时,内存可能会被耗尽。如果数据文件太大,则将它设置为True
  • save_binary, [default=1]
    表示是否将数据集(包括验证集)保存到二进制文件中。默认值为False。如果为True,则可以加快数据的加载速度。
  • verbosity, [default=1]
    表示是否输出中间信息。默认值为1。如果小于0,则仅仅输出critical 信息;如果等于0,则还会输出error,warning 信息; 如果大于0,则还会输出info 信息。

  • header, [default=false]
    如果输入数据有标识头, 则在此处设置 true

  • label , [default=””]
    表示标签列。默认为空字符串。你也可以指定一个整数,如label=0 表示第0列是标签列。你也可以为列名添加前缀,如label=prefix:label_name
  • weight , [default=””]
    一个字符串,表示样本权重列。默认为空字符串。你也可以指定一个整数,如weight=0 表示第0列是权重列。注意:它是剔除了标签列之后的索引。假如标签列为0,权重列为1,则这里weight=0。你也可以为列名添加前缀,如weight=prefix:weight_name
  • query, [default=””]
    表示query/group ID 列。
  • ignore_column , [default=””]
    表示训练中忽略的一些列,默认为空字符串。可以用数字做索引,如ignore_column=0,1,2 表示第0,1,2 列将被忽略。注意:它是剔除了标签列之后的索引。
  • categorical_feature, [default=””]
    指定category 特征的列。默认为空字符串。可以用数字做索引,如categorical_feature=0,1,2 表示第0,1,2 列将作为category 特征。注意:它是剔除了标签列之后的索引。你也可以为列名添加前缀,如categorical_feature=prefix:cat_name1,cat_name2 在categorycal 特征中,负的取值被视作缺失值。
  • predict_leaf_index[default=false]
    表示是否预测每个样本在每棵树上的叶节点编号。默认为False。在预测时,每个样本都会被分配到每棵树的某个叶子节点上。该参数就是要输出这些叶子节点的编号。该参数只用于prediction 任务。
  • bin_construct_sample_cnt [default=200000]
    表示用来构建直方图的样本的数量。默认为200000。如果数据非常稀疏,则可以设置为一个更大的值,如果设置更大的值,则会提供更好的训练效果,但是会增加数据加载时间。
  • num_iteration_predict[default=-1]
    表示在预测中使用多少棵子树。默认为-1。小于等于0表示使用模型的所有子树。该参数只用于prediction 任务。

Objective Parameters(目标参数)

  • sigmoid[default=1]
    sigmoid 函数的参数. 将用于 binary 分类 和 lambdarank。
  • scale_pos_weight[default=1]
    用于调整正样本的权重,默认值为0,用于二分类任务。
  • is_unbalance[default=false]
    指示训练数据是否均衡的。默认为True。用于二分类任务。
  • num_class[default=1]
    指示了多分类任务中的类别数量。默认为1,用于多分类任务。
  • reg_sqrt[default=false]
    一个布尔值,默认为False。如果为True,则拟合的结果为:$\sqrt{label}$。同时预测的结果被自动转换为:${pred}^2$。它用于回归任务。

Metric Parameters(度量参数)

  • metric[default={l2 for regression}, {binary_logloss for binary classification}, {ndcg for lambdarank}]
    度量的指标,默认为:对于回归问题,使用l2 ;对于二分类问题,使用binary_logloss;对于lambdarank 问题,使用ndcg。如果有多个度量指标,则用逗号, 分隔。
    • ‘l1’ 或者 mean_absolute_error或者 mae或者 regression_l1: 表示绝对值损失
    • ‘l2’ 或者mean_squared_error或者 mse或者 regression_l2或者 regression:表示平方损失
    • ‘l2_root’ 或者root_mean_squared_error或者 rmse:表示开方损失
    • ‘quantile’: 表示Quantile 回归中的损失
    • ‘mape’ 或者 ‘mean_absolute_percentage_error’ :表示MAPE 损失
    • ‘map’ 或者’mean_average_precision’: 表示平均的精度
    • ‘auc’: 表示AUC
    • ‘binary_logloss’或者’binary’: 表示二类分类中的对数损失函数
    • ‘binary_error’: 表示二类分类中的分类错误率
    • ‘multi_logloss’或者 ‘multiclass’或者 ‘softmax’或者 ‘multiclassova’或者 ‘multiclass_ova’,或者’ova’或者 ‘ovr’: 表示多类分类中的对数损失函数
    • ‘multi_error’: 表示多分类中的分类错误率
    • ‘xentropy’或者’cross_entropy’: 表示交叉熵
    • ‘xentlambda’ 或者’cross_entropy_lambda’: 表示intensity 加权的交叉熵
    • ‘kldiv’或者’kullback_leibler’: 表示KL 散度
  • metric_freq[default=1]
    每隔多少次输出一次度量结果。默认为1。
  • train_metric [default=false]
    如果为True,则在训练时就输出度量结果。

调参方法

针对 leaf-wise 树的参数优化

  • num_leaves:控制了叶节点的数目。它是控制树模型复杂度的主要参数。

    如果是level-wise,则该参数为$2^{depth}$,其中$depth$为树的深度。但是当叶子数量相同时,leaf-wise的树要远远深过level-wise树,非常容易导致过拟合。因此应该让num_leaves小于$2^{depth}$。在leaf-wise树中,并不存在$depth$的概念。因为不存在一个从$leaves$到$depth$的合理映射。

  • min_data_in_leaf:每个叶节点的最少样本数量。它是处理leaf-wise树的过拟合的重要参数。将它设为较大的值,可以避免生成一个过深的树。但是也可能导致欠拟合。
  • max_depth: 控制了树的最大深度。该参数可以显式的限制树的深度。

针对更快的训练速度

  • 通过设置 bagging_fraction 和 bagging_freq 参数来使用 bagging 方法
  • 通过设置 feature_fraction 参数来使用特征的子抽样
  • 使用较小的 max_bin
  • 使用 save_binary 在未来的学习过程对数据加载进行加速

获取更好的准确率

  • 使用较大的 max_bin (学习速度可能变慢)
  • 使用较小的 learning_rate 和较大的 num_iterations
  • 使用较大的 num_leaves (可能导致过拟合)
  • 使用更大的训练数据
  • 尝试 dart

缓解过拟合

  • 使用较小的 max_bin
  • 使用较小的 num_leaves
  • 使用 min_data_in_leaf 和 min_sum_hessian_in_leaf
  • 通过设置 bagging_fraction 和 bagging_freq 来使用 bagging
  • 通过设置 feature_fraction 来使用特征子抽样
  • 使用更大的训练数据
  • 使用 lambda_l1, lambda_l2 和 min_gain_to_split 来使用正则
  • 尝试 max_depth 来避免生成过深的树